package com.share.common.utils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @author 01401061 - 孙艳强
 * @date 2020/10/30 18:56
 */
public class DateExtUtil {
    //开盘时间
    public static final int time0930 = new Integer("09:30:00".replaceAll(":", ""));
    public static final int time1130 = new Integer("11:30:00".replaceAll(":", ""));
    public static final int time1300 = new Integer("13:00:00".replaceAll(":", ""));
    public static final int time1500 = new Integer("15:00:00".replaceAll(":", ""));

    // 时区
    public static final ZoneId zoneId = ZoneId.systemDefault();
    public static final TimeZone timeZone = TimeZone.getTimeZone(zoneId);

    public static final String DEFAULT_DAY = "20200101";
    public static final String TIME_BEGIN = "000000";
    public static final String TIME_END = "235959";

    // 默认日期格式---禁止其他类型---这是标准
    public static final String YYYY = "yyyy";
    public static final String YYYYMM = "yyyyMM";
    public static final String YYYYMMDD = "yyyyMMdd";
    public static final String HHMMSS = "HHmmss";
    public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";

    //DateTimeFormatter线程安全
    private final static DateTimeFormatter dtfYear = DateTimeFormatter.ofPattern(YYYY);
    private final static DateTimeFormatter dtfYearMonth = DateTimeFormatter.ofPattern(YYYYMM);
    private final static DateTimeFormatter dtfDate = DateTimeFormatter.ofPattern(YYYYMMDD);
    private final static DateTimeFormatter dtfTime = DateTimeFormatter.ofPattern(HHMMSS);
    private final static DateTimeFormatter dtfDateTime = DateTimeFormatter.ofPattern(YYYYMMDDHHMMSS);
    private final static Map<String, DateTimeFormatter> dtfMap = new HashMap<>();

    static {
        dtfMap.put(YYYY, dtfYear);
        dtfMap.put(YYYYMM, dtfYearMonth);
        dtfMap.put(YYYYMMDD, dtfDate);
        dtfMap.put(HHMMSS, dtfTime);
        dtfMap.put(YYYYMMDDHHMMSS, dtfDateTime);
    }

    private static Calendar getCalendar() {
        Calendar cal = Calendar.getInstance();
        cal.setTimeZone(timeZone);
        return cal;
    }

    private static LocalDate nowDate() {
        return LocalDate.now(zoneId);
    }

    private static LocalDateTime nowDateTime() {
        return LocalDateTime.now(zoneId);
    }

    private static Date localDateTime2Date(LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(zoneId).toInstant());
    }

    private static LocalDateTime date2LocalDateTime(Date date) {
        return date.toInstant().atZone(zoneId).toLocalDateTime();
    }

    //date转str
    public static String getDate() {
        return getDate(new Date(), 0);
    }

    public static String getDateTime() {
        return getDateTime(new Date(), 0);
    }

    public static String getDate(int addDay) {
        return getDate(new Date(), addDay);
    }

    public static String getDateTimeBegin(int addDay) {
        return getDate(addDay) + TIME_BEGIN;
    }

    public static String getDateTimeEnd(int addDay) {
        return getDate(addDay) + TIME_END;
    }

    public static String getDateTime(int addDay) {
        return getDateTime(new Date(), addDay);
    }

    public static String getDate(Date date, int addDay) {
        return dateToStr(date, YYYYMMDD);
    }

    public static String getDateTime(Date date, int addDay) {
        return dateToStr(date, YYYYMMDDHHMMSS);
    }

    public static String getDate(Date date) {
        return dateToStr(date, YYYYMMDD);
    }

    public static String getYearMonth(Date date) {
        return dateToStr(date, YYYYMM);
    }

    public static int compareYearMonth(Date date1, Date date2) {
        return compare(date1, date2, YYYYMM);
    }

    public static int compareDate(Date date1, Date date2) {
        return compare(date1, date2, YYYYMMDD);
    }

    public static int compareDateTime(Date date1, Date date2) {
        return compare(date1, date2, YYYYMMDDHHMMSS);
    }

    public static int compare(Date date1, Date date2, String format) {
        if (date1 == null && date2 == null) {
            return 0;
        } else if (date1 == null) {
            return -1;
        } else if (date2 == null) {
            return 1;
        } else {
            String s1 = dateToStr(date1, format);
            String s2 = dateToStr(date2, format);
            return s1.compareTo(s2);
        }
    }

    public static String getDateTime(Date date) {
        return dateToStr(date, YYYYMMDDHHMMSS);
    }

    public static String getTime() {
        return dateToStr(new Date(), HHMMSS);
    }

    public static String getTime(Date date) {
        return dateToStr(date, HHMMSS);
    }

    /**
     * 把时间字符串转为整数
     * <p>
     * 例如：
     * 000000 会变成 0
     * 100000 会变成 100000
     *
     * @param date
     * @return
     */
    public static Integer getTimeInt(Date date) {
        return new Integer(dateToStr(date, HHMMSS));
    }

    /**
     * 返回今天周几
     * 周一返回1
     * 周六返回6
     * 周日返回7
     *
     * @param date
     * @return
     */
    public static int getDayOfWeek(Date date) {
        return date2LocalDateTime(date).getDayOfWeek().getValue();
    }

    public static String dateToStr(Date date, String format) {
        return date2LocalDateTime(date).format(dtfMap.get(format));
    }

    public static Date strDT2Date(String str) {
        return strToDate(str, YYYYMMDDHHMMSS);
    }

    public static Date strD2Date(String str) {
        return strToDate(str, YYYYMMDD);
    }

    public static Date strToDate(String str, String format) {
        String tmpStr = null;
        DateTimeFormatter dtf = null;
        switch (format) {
            case YYYYMMDDHHMMSS:
                tmpStr = str;
                dtf = dtfMap.get(format);
                break;

            case YYYYMMDD:
                tmpStr = str + TIME_BEGIN;
                dtf = dtfMap.get(YYYYMMDDHHMMSS);//追加了长度,改变类型
                break;

            case HHMMSS:
                tmpStr = DEFAULT_DAY + str;
                dtf = dtfMap.get(YYYYMMDDHHMMSS);//追加了长度,改变类型
                break;

            case YYYYMM:
                tmpStr = str + "01" + TIME_BEGIN;
                dtf = dtfMap.get(YYYYMMDDHHMMSS);//追加了长度,改变类型
                break;
            case YYYY:
                tmpStr = str + "0101" + TIME_BEGIN;
                dtf = dtfMap.get(YYYYMMDDHHMMSS);//追加了长度,改变类型
                break;
            default:
                return null;
        }

        //先格式转换
        return localDateTime2Date(LocalDateTime.parse(tmpStr, dtf));
    }

    public static Date addDay(int addDay) {
        return calcDate(new Date(), null, null, addDay, null, null, null);
    }

    public static Date addDay(Date date, int addDay) {
        return calcDate(date, null, null, addDay, null, null, null);
    }

    public static Date addMonth(int addMonth) {
        return calcDate(new Date(), null, addMonth, null, null, null, null);
    }

    public static Date addMonth(Date date, int addMonth) {
        return calcDate(date, null, addMonth, null, null, null, null);
    }

    //对date进行计算
    private static Date calcDate(Date date, Integer addYear, Integer addMonth, Integer addDay, Integer addHour, Integer addMinute, Integer addSecond) {
        Calendar cal = getCalendar();
        cal.setTime(date);
        if (addYear != null) {
            cal.add(Calendar.YEAR, addYear);
        }
        if (addMonth != null) {
            cal.add(Calendar.MONTH, addMonth);
        }
        if (addDay != null) {
            cal.add(Calendar.DAY_OF_YEAR, addDay);
        }

        if (addHour != null) {
            cal.add(Calendar.HOUR_OF_DAY, addHour);
        }

        if (addMinute != null) {
            cal.add(Calendar.MINUTE, addMinute);
        }

        if (addSecond != null) {
            cal.add(Calendar.SECOND, addSecond);
        }
        return cal.getTime();
    }

    public static void main(String[] args) {
        String time = getTime();
        System.out.println(time);
        System.out.println(getDayOfWeek(strToDate("20230602", YYYYMMDD)));
        System.out.println(addMonth(new Date(), 1));
    }
}
